from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View
import jwt
from myapp.models import User
import json

from rest_framework.response import Response
from rest_framework.views import APIView
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

import requests

# 导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid
from myapp.myser import UserSer
import redis
from django.utils.deprecation import MiddlewareMixin

# 定义地址和端口
host = '127.0.0.1'
port = 6379
# 建立redis连接
r = redis.Redis(host=host, port=port)


# 装饰器
def my_decorator(func):
    def wrapper(request, *args, **kwargs):
        # print('这个装饰器被调用了')
        # print('请求地址是%s' % request.path)
        # 判断jwt逻辑
        # uid = request.GET.get('uid')
        # cline_jwt = request.GET.get('jwt', None)
        # decode_jwt = jwt.decode(cline_jwt, '123', algorithms=['HS256'])
        # if decode_jwt['uid'] != str(uid):
        #     return HttpResponse('你篡改了用户id')
        return func(request, *args, **kwargs)

    return wrapper


# 类装饰器调用
from django.utils.decorators import method_decorator


# 自定义中间件类
class MyMiddleWare(MiddlewareMixin):
    # 请求之前
    def process_request(self, request):
        # uid = request.GET.get('uid')
        # cline_jwt = request.GET.get('jwt',None)
        # if cline_jwt == None:
        #     return HttpResponse('你没有带上令牌')
        # decode_jwt = jwt.decode(cline_jwt, '123', algorithms=['HS256'])
        # if decode_jwt['uid'] != str(uid):
        #     return HttpResponse('你篡改了用户id')
        pass

    def process_view(self, request, view_func, view_args, view_kwargs):
        pass

    # 请求之后
    def process_response(self, request, response):
        return response


# 更新用户头像
class Update_user_img(APIView):
    def get(self, request):
        img = request.GET.get("img")
        uid = request.GET.get("uid")
        # 查询数据
        user = User.objects.get(id=int(uid))
        user.img = img
        user.save()
        return Response({'code': 200, 'message': "更新成功"})


# 用户信息类
class UserInfo(APIView):
    # 把装饰器转换成适用于类视图
    @method_decorator(my_decorator)
    def get(self, request):
        uid = request.GET.get("uid")
        # 查询数据
        user = User.objects.get(id=int(uid))
        # 序列化对象
        user_ser = UserSer(user)
        return Response(user_ser.data)


# 更新用户视频
class Update_user_video(APIView):
    def get(self, request):
        img = request.GET.get("img")
        uid = request.GET.get("uid")
        # 查询数据
        user = User.objects.get(id=int(uid))
        user.video = img
        user.save()
        return Response({'code': 200, 'message': "更新成功"})


# 七牛云密钥接口
from qiniu import Auth


class QiNiu(APIView):
    def get(self, requests):
        # 声明密钥对象
        q = Auth('XqTiNdtbf7ncW7HLn5Un-KjvE6rJatJFwi9zSy4e', 'U1UCK6D6mW25QQ-EKwKpjdMOWUwBoMMwmbS1Si3r')
        # 生成令牌
        token = q.upload_token('wangxin123')
        return Response({'uptoken': token})


# 密码修改
class UpdateUser(APIView):
    def get(self, request):
        uid = request.GET.get('uid')
        password = request.GET.get('password')
        # 在数据库中查找
        user = User.objects.get(id=int(uid))
        res = {}
        if user.password != make_password(password):
            user.password = make_password(password)
            user.save()
            res['code'] = 200
            res['msg'] = '修改成功'
        else:
            res['code'] = 405
            res['msg'] = '密码不能与原密码相同'
        return Response(res)


# 定义上传视图类
class UploadFile(View):
    def post(self, request):
        # 接收参数
        img = request.FILES.get('file')
        # 建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT, '', img.name), 'wb')
        # 写入服务端
        for chunk in img.chunks():
            f.write(chunk)
        f.close()
        # 打开图片
        im = Image.open(img)
        # 指定要使用的字体和大小；
        font = ImageFont.truetype('C:\\Windows\\Fonts\\simsun.ttc', size=40)
        # 生成画笔对象
        draw = ImageDraw.Draw(im)
        # 修改图片
        draw.text((10, 10), '王鑫', fill=(76, 234, 124, 180), font=font)
        im.save('./static/upload/' + img.name)
        # 返回文件名
        return HttpResponse(json.dumps({'filename': img.name}, ensure_ascii=False), content_type='application/json')


import time
import hmac
import base64
from hashlib import sha256
import urllib


# 构造钉钉回调方法
def ding_back(request):
    # 获取code
    code = request.GET.get("code")

    t = time.time()
    # 时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret = 'ly-AzMKMmCKQP3geaILT_An32kEfKO3HeOtApy5CgKwjytevVZC0WYsT2gxMB160'
    # 构造签名
    signature = base64.b64encode(
        hmac.new(appSecret.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
    # 请求接口，换取钉钉用户名
    payload = {'tmp_auth_code': code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature=' + urllib.parse.quote(
        signature.decode("utf-8")) + "&timestamp=" + timestamp + "&accessKey=dingoaukgkwqknzjvamdqh",
                        data=json.dumps(payload), headers=headers)

    res_dict = json.loads(res.text)
    print(res_dict['user_info']['nick'])
    # 判断是否用钉钉登陆过
    user = User.objects.filter(username=str(res_dict['user_info']['nick'])).first()

    ding_id = ''
    user_id = ''

    if user:
        # 代表登陆过
        ding_id = user.username
        user_id = user.id
    else:
        # 自动创建账号
        user = User(username=str(res_dict['user_info']['nick']), password='', type=0)
        # 保存
        user.save()
        # 查询用户id
        user = User.objects.filter(username=str(res_dict['user_info']['nick'])).first()

        ding_id = str(res_dict['user_info']['nick'])
        user_id = user.id
    # 跳转操作
    return redirect('http://localhost:8080?ding_id=' + str(ding_id) + "&uid=" + str(user_id))


# 新浪微博回调
def wb_back(request):
    # 获取code
    code = request.GET.get('code')
    # 定义微博认证地址
    access_token_url = "https://api.weibo.com/oauth2/access_token"

    # 发送请求进行换取
    res = requests.post(
        access_token_url,
        data={
            "client_id": '4048655952',
            "client_secret": "582b5db23af403823f2ad126f8abbd68",
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": "http://127.0.0.1:8000/md_admin/weibo"
        })
    # 转换类型
    res = json.loads(res.text)

    # 换取新浪微博昵称 json
    result = requests.get('https://api.weibo.com/2/users/show.json',
                          params={'access_token': res['access_token'], 'uid': res['uid']})

    result = json.loads(result.text)

    # 判断该用户是否曾经登录过
    user = User.objects.filter(username=str(result['name'])).first()

    sina_id = ''
    user_id = ''

    if user:
        sina_id = user.username
        user_id = user.id
    else:
        # 手创建账号
        user = User(username=str(result['name']), password='', type=0)
        user.save()

        sina_id = result['name']

        # 查询一下刚刚入库的新账号id
        user = User.objects.filter(username=str(result['name'])).first()
        user_id = user.id

    return redirect("http://localhost:8080?sina_id=" + sina_id + "&uid=" + str(user_id))


# 定义验证码类
class MyCode(View):
    # 定义随机颜色
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R, G, B)

    # 获取验证码视图
    def get(self, request):
        # 画布
        img_size = (120, 60)
        # 定义图画对象
        image = Image.new('RGB', img_size, 'white')
        # 定义画笔对象
        draw = ImageDraw.Draw(image, 'RGB')
        # 定义随机字符串
        source = ('福', '如', '东', '海', '寿', '比', '南', '山', '财', '源', '滚', '出', '年', '都', '有', '鱼')
        # 容器
        code_str = ''
        # 定义字体
        my_font = ImageFont.truetype(font="C:\\Windows\\Fonts\\simfang.ttf", size=20)
        for i in range(4):
            # 获取随机颜色
            text_color = self.get_random_color()
            # 获取随机字符串长度下标
            tmp_num = random.randrange(len(source))
            # 获取字符集
            random_str = source[tmp_num]
            # 添加到容器中
            code_str += random_str
            # 将字符串添加到画布上
            draw.text((10 + 30 * i, 20), random_str, text_color, font=my_font)
        # 建立缓存区
        buf = io.BytesIO()
        # 将验证码存储到redis中
        r.set('code', code_str)
        # 将验证码存储到session中
        request.session['code'] = code_str
        # 保存图片
        image.save(buf, 'png')
        return HttpResponse(buf.getvalue(), 'image/png')


# md5加密方法
def make_password(mypass):
    # 生成md5对象
    md5 = hashlib.md5()
    # 定义加密对象
    sign_str = mypass
    # 转码
    sign_utf8 = str(sign_str).encode(encoding="utf-8")
    # 加密操作
    md5.update(sign_utf8)
    # 生成密文
    md5_server = md5.hexdigest()
    return md5_server


# 注册模块
class Register(APIView):

    def get(self, request):
        # 接收参数
        username = request.GET.get('username', 'null')
        password = request.GET.get('password', 'null')
        code = request.GET.get('code', 'null')

        # 从session中获取验证码
        session_code = request.session.get('code', None)
        print(session_code)

        # 获取验证码
        redis_code = r.get('code')
        # 转码
        redis_code = redis_code.decode('utf-8')
        print(redis_code)
        # 判断验证码是否正确
        if redis_code != code:
            res = {}
            res['code'] = 405
            res['message'] = '验证码输入错误'
            return Response(res)
        # 排重操作
        user = User.objects.filter(username=username).first()
        if user:
            res = {}
            res['code'] = 405
            res['message'] = '用户已经存在'
            return Response(res)

        # 进行入库操作
        user = User(username=username, password=make_password(password), img='', type=0, video='')
        # 保存
        user.save()

        # 返回结果
        res = {}
        res['code'] = 200
        res['message'] = '注册成功'
        return Response(res)


class Login(APIView):
    def get(self, request):
        # 接收参数
        username = request.GET.get('username')
        password = request.GET.get('password')
        # 查询数据
        user = User.objects.filter(username=username, password=make_password(password)).first()
        if user:
            res = {}
            res['code'] = 200
            res['message'] = '登录成功'
            res['username'] = user.username
            res['uid'] = user.id
            # 加入jwt令牌机制
            encode_jwt = jwt.encode({'uid': str(user.id)}, '123', algorithm='HS256')
            # 强转
            encode_str = str(encode_jwt, 'utf-8')
            res['jwt'] = encode_str
            return Response(res)
        else:
            res = {}
            res['code'] = 405
            res['message'] = '用户名或密码错误'
            return Response(res)
